//
//  NuInternals.h
//  Nu
//
//  Created by Tim Burks on 4/24/16.
//

#ifndef NuInternals_h
#define NuInternals_h

#define NU_VERSION "2.3.0"
#define NU_VERSION_MAJOR 2
#define NU_VERSION_MINOR 3
#define NU_VERSION_TWEAK 0
#define NU_RELEASE_DATE "2019-07-28"
#define NU_RELEASE_YEAR  2019
#define NU_RELEASE_MONTH 07
#define NU_RELEASE_DAY   28

#import "Nu.h"

@class NuBlock;

#define IS_NOT_NULL(xyz) ((xyz) && (((id) (xyz)) != Nu__null))


extern NSMutableDictionary *nu_block_table;

extern id Nu__null;

// Execution contexts are NSMutableDictionaries that are keyed by
// symbols.  Here we define two string keys that allow us to store
// some extra information in our contexts.

// Use this key to get the symbol table from an execution context.
#define SYMBOLS_KEY @"symbols"

// Use this key to get the parent context of an execution context.
#define PARENT_KEY @"parent"

/*!
 @class NuBreakException
 @abstract Internal class used to implement the Nu break operator.
 */
@interface NuBreakException : NSException
@end

/*!
 @class NuContinueException
 @abstract Internal class used to implement the Nu continue operator.
 */
@interface NuContinueException : NSException
@end

/*!
 @class NuReturnException
 @abstract Internal class used to implement the Nu return operator.
 */
@interface NuReturnException : NSException
{
    id value;
    id blockForReturn;
}

- (id) value;
- (id) blockForReturn;
@end

// use this to test a value for "truth"
bool nu_valueIsTrue(id value);

// use this to get the filename for a NuCell created by the parser
const char *nu_parsedFilename(int i);



id nu_calling_objc_method_handler(id target, Method m, NSMutableArray *args);


// We'd like for this to be in the ObjC2 API, but it isn't.
void nu_class_addInstanceVariable_withSignature(Class thisClass, const char *variableName, const char *signature);

// These are handy.
IMP nu_class_replaceMethod(Class cls, SEL name, IMP imp, const char *types);
BOOL nu_copyInstanceMethod(Class destinationClass, Class sourceClass, SEL selector);
BOOL nu_objectIsKindOfClass(id object, Class class);
void nu_markEndOfObjCTypeString(char *type, size_t len);

// This makes it safe to insert nil into container classes
void nu_swizzleContainerClasses(void);

id add_method_to_class(Class c, NSString *methodName, NSString *signature, NuBlock *block);
id get_nu_value_from_objc_value(void *objc_value, const char *typeString);
int set_objc_value_from_nu_value(void *objc_value, id nu_value, const char *typeString);
void *value_buffer_for_objc_type(const char *typeString);
NSString *signature_for_identifier(NuCell *cell, NuSymbolTable *symbolTable);
id help_add_method_to_class(Class classToExtend, id cdr, NSMutableDictionary *context, BOOL addClassMethod);
size_t size_of_objc_type(const char *typeString);


#pragma mark - DTrace macros

/*
 * Generated by dtrace(1M).
 */

#ifndef	_DTRACE_H
#define	_DTRACE_H

#include <unistd.h>

#ifdef	__cplusplus
extern "C" {
#endif
    
#define NU_STABILITY "___dtrace_stability$nu$v1$5_5_5_1_1_5_1_1_5_5_5_5_5_5_5"
    
#define NU_TYPEDEFS "___dtrace_typedefs$nu$v1"
    
#define	NU_LIST_EVAL_BEGIN(arg0, arg1) \
{ \
__asm__ volatile(".reference " NU_TYPEDEFS); \
__dtrace_probe$nu$list_eval_begin$v1$63686172202a$696e74((char *)arg0, arg1); \
__asm__ volatile(".reference " NU_STABILITY); \
}
#define	NU_LIST_EVAL_BEGIN_ENABLED() \
__dtrace_isenabled$nu$list_eval_begin$v1()
#define	NU_LIST_EVAL_END(arg0, arg1) \
{ \
__asm__ volatile(".reference " NU_TYPEDEFS); \
__dtrace_probe$nu$list_eval_end$v1$63686172202a$696e74((char *)arg0, arg1); \
__asm__ volatile(".reference " NU_STABILITY); \
}
#define	NU_LIST_EVAL_END_ENABLED() \
__dtrace_isenabled$nu$list_eval_end$v1()
    
    
    extern void __dtrace_probe$nu$list_eval_begin$v1$63686172202a$696e74(char *, int);
    extern int __dtrace_isenabled$nu$list_eval_begin$v1(void);
    extern void __dtrace_probe$nu$list_eval_end$v1$63686172202a$696e74(char *, int);
    extern int __dtrace_isenabled$nu$list_eval_end$v1(void);
    
#ifdef	__cplusplus
}
#endif

#endif	/* _DTRACE_H */

#endif /* NuInternals_h */
